package com.yu8home.asyc.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * https://cloud.tencent.com/developer/article/1909426
 * https://www.cnblogs.com/dxflqm/p/18074723
 * <pre>
 * Spring 的默认线程池配置
 * 注意早期版本的Spring Boot环境中，如果用户没有自定义配置异步执行器（Async Executor），并且没有实现AsyncConfigurer接口来提供一个自定义的执行器，那么Spring Boot会使用一个默认的异步执行器，而在某些早期版本或特定配置下，这个默认执行器可能是SimpleAsyncTaskExecutor，这是个不重用线程、无界并发的执行器。每个提交的任务创建一个新的线程来执行。这意味着每次调用都会创建新的线程资源，而不从固定大小的线程池中获取可用线程。
 * 在后期版本中，如果没有 Executor 的实例 Spring Boot将会使用其默认配置的线程池（名称为 taskExecutor）来执行被@Async注解修饰的异步方法。
 * 在Spring Boot如果不存在 Excutor Bean 会通过TaskExecutionAutoConfiguration，它会自动配置一个基于ThreadPoolTaskExecutor的默认线程池，取名为applicationTaskExecutor 和 taskExecutor 进行自动配置。如果已经自定义了Executor bean 那么applicationTaskExecutor将不会自动配置。
 *
 * 这个默认线程池的相关配置通常基于Spring Boot的默认属性这些属性可以根据应用的具体需求，在application.properties或application.yml文件中进行调整：
 * spring.task.execution.pool.core-size：核心线程数，默认值可能依赖于具体版本，一般较小。
 * spring.task.execution.pool.max-size：最大线程数，默认值也可能因版本不同而变化。
 * spring.task.execution.pool.queue-capacity：线程池的工作队列容量。
 * spring.task.execution.pool.keep-alive：空闲线程的存活时间。
 * </pre>
 */
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    private static final int CORE_POOL_SIZE = 6;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;

    // 在Spring容器中注册一个线程池Bean，这种方式允许你根据业务需求更加灵活地管理和分配不同的线程池资源。
    @Bean("taskExecutor")
    // @Async("taskExecutor")
    public Executor taskExecutor() {
        return null;
    }

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(CORE_POOL_SIZE);
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        executor.setQueueCapacity(QUEUE_CAPACITY);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 当最大池已满时，此策略保证不会丢失任务请求，但是可能会影响应用程序整体性能
        executor.setThreadNamePrefix("aaaaaaa-");
        executor.initialize();
        return executor;
    }

}
